package com.zj.filters;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;

/**
 * @program: shopping153_cloud
 * @description:
 * @author: zy
 * @create: 2025-08-29 14:17
 */
public class JwtAuthorizationFilter extends OncePerRequestFilter  {
    // Gateway 传递用户ID的请求头名称
    private static final String USER_ID_HEADER = "X-MyUser-ID";
    private static final String USER_NAME_HEADER = "X-MyUser-Name";
    // Gateway 传递用户角色（逗号分隔）的请求头名称
    private static final String USER_ROLES_HEADER = "X-MyUser-Roles";

    //能从gateway将请求转到user服务上来，就说明 这个token是有效的，且已经解析好了，以上面三个请求头的方式传递过来了
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //获取 token, 解析token, 得到  userid, username, roles,  ->ｇａｔｅｗａｙ　存到ｈｅａｄｅｒ　
        // http中可以使用X-xxx扩展头信息， 可以用来传递额外的信息.
        // 样验 ， 将过滤器向后传递.
        // 1. 从请求头中获取用户ID和角色信息
        String userId = request.getHeader(USER_ID_HEADER);
        String userRoles = request.getHeader(USER_ROLES_HEADER);
        String username=request.getHeader(USER_NAME_HEADER);

        // 2. 如果用户信息存在，则构建 Spring Security 的认证对象
        if (userId != null && !userId.trim().isEmpty() && userRoles != null && !userRoles.trim().isEmpty()) {
            // 将逗号分隔的角色字符串转换为 GrantedAuthority 集合
            Collection<? extends GrantedAuthority> authorities =
                    Arrays.stream(userRoles.split(","))
                            .map(role -> new SimpleGrantedAuthority("ROLE_" + role.trim().toUpperCase())) // Spring Security 角色前缀为 ROLE_
                            .collect(Collectors.toList());
            // 创建认证令牌。这里使用 userId 作为 principal，密码为 null，并传入权限列表。
            // 密码为 null 是因为认证已经在 Gateway 完成，这里只是设置授权信息。
            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(userId, null, authorities);   // authentication.principal=userId
            // 将认证对象设置到 SecurityContextHolder，供后续的授权检查使用 -> 在后面的controller中以注解方式来获取这个用户的权限信息，
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        // 3. 继续过滤器链  返回controller
        filterChain.doFilter(request, response);
    }
}
